package cn.bigfire.wedesk.net.codec;

import cn.bigfire.wedesk.net.protocol.Protocol;
import cn.bigfire.wedesk.net.protocol.TypeMapper;
import cn.bigfire.wedesk.util.ByteUtil;
import cn.bigfire.wedesk.util.ProtostuffUtil;
import com.alibaba.fastjson.JSON;
import com.google.protobuf.AbstractMessage;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;

/**
 * 业务层 编解码器 编码和解码放在同一个类里
 */
@Deprecated
public class ProtocolWebSocketCodec extends ChannelDuplexHandler {

    //解码
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        try {
            Protocol protocol = new Protocol();
            if (msg instanceof TextWebSocketFrame) {
                TextWebSocketFrame textWebSocketFrame = (TextWebSocketFrame) msg;
                protocol = JSON.parseObject(textWebSocketFrame.text(), Protocol.class);
                System.out.printf("->cmd:%s,type:%s,len:%s[%s]%n", protocol.getCmd(), protocol.getType(), textWebSocketFrame.text().length(), ByteUtil.size(textWebSocketFrame.text().length()));
                if (protocol.getCmd() != 0 && protocol.getObj() != null) {//有效数据再往下传递
                    ctx.fireChannelRead(protocol);
                }
            } else if (msg instanceof BinaryWebSocketFrame) {
                BinaryWebSocketFrame binaryWebSocketFrame = (BinaryWebSocketFrame) msg;
                ByteBuf content = binaryWebSocketFrame.content();
                int cmd = content.readInt();
                int type = content.readInt();
                byte[] bytes = new byte[content.readableBytes()];
                content.readBytes(bytes);
                protocol.setCmd(cmd);
                protocol.setType(type);
                Class<?> codec = TypeMapper.getCodec(type);
                protocol.setObj(ProtostuffUtil.deserializer(bytes, codec));
                if (protocol.getCmd() != 0 && protocol.getObj() != null) {//有效数据再往下传递
                    System.out.printf("->cmd:%s,type:%s,len:%s[%s]%n", protocol.getCmd(), protocol.getType(), bytes.length, ByteUtil.size(bytes.length));
                    ctx.fireChannelRead(protocol);
                }
            } else {
                ctx.fireChannelRead(msg);
                System.err.println("不能解码的类型" + msg.getClass().getName());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    boolean isJson = false;//控制写数据时使用protobuf还是json
    //编码
    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        try {
            if (msg instanceof Protocol) {
                Protocol protocol = (Protocol) msg;
                if (isJson) {
                    String jsonString = JSON.toJSONString(protocol);
                    System.out.printf("->cmd:%s,type:%s,len:%s[%s]%n", protocol.getCmd(), protocol.getType(), jsonString.length(), ByteUtil.size(jsonString.length()));
                    TextWebSocketFrame textWebSocketFrame = new TextWebSocketFrame(jsonString);
                    super.write(ctx, textWebSocketFrame, promise);
                } else {
                    int cmd = protocol.getCmd();
                    int type = TypeMapper.getType(protocol.getObj().getClass());
                    byte[] bytes = new byte[0];
                    if (protocol.getObj() instanceof AbstractMessage) {
                        AbstractMessage abstractMessage = (AbstractMessage) protocol.getObj();
                        bytes = abstractMessage.toByteArray();
                    } else {
                        bytes = ProtostuffUtil.serializer(protocol.getObj());
                    }
                    ByteBuf outBuf = Unpooled.buffer();
                    outBuf.writeInt(cmd);
                    outBuf.writeInt(type);
                    outBuf.writeBytes(bytes);
                    System.out.printf("->cmd:%s,type:%s,len:%s[%s]%n", protocol.getCmd(), protocol.getType(), bytes.length, ByteUtil.size(bytes.length));
                    BinaryWebSocketFrame binaryWebSocketFrame = new BinaryWebSocketFrame(outBuf);
                    super.write(ctx, binaryWebSocketFrame, promise);
                }
            } else {
                System.err.println("不能编码的类型" + msg.getClass().getName());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
